/*
 * ColaRemotaReceptor.h
 *
 *  Created on: Dec 13, 2013
 *      Author: m
 */

#ifndef COLAREMOTARECEPTOR_H_
#define COLAREMOTARECEPTOR_H_

#include <cstdlib>
#include <fstream>
#include <cstring>
#include "ColaRemotaComun.h"
#include "DNSService.h"
#include "NumeradorService.h"
#include "Exception.h"
#include "StringUtils.h"
#include <unistd.h>
#include "ArchivoIni.h"
#include "StringUtils.h"

#define CONFIG_FILE "config.ini"

class ColaRemotaReceptor
{
protected:
    std::string m_nombreColaRemota;
    int m_socket;

    void _conectar()
    {
        // Me conecto al servidor de Salida
        std::string server;
        int descarto;
        int puertoSalida = 0;
        int idCola;

        // Leer la direccion del broker de otro archivo
        std::ifstream input ("brokerlist");
        if ( !input )
        {
            throw Exception( "ColaRemotaReceptor: Error al abrir la lista de brokers");
        }
        input >> server;
        input.close();


        // Leer el puerto del servicio de un archivo
        ArchivoIni configFile( CONFIG_FILE );
        puertoSalida = StringUtils::StringToNumber<int>( configFile.getValue( "puertoSalida" ) );

        // Me conecto al puerto de Entrada del servidor.
        m_socket = tcpopact( server.c_str(), puertoSalida );

        // Obtengo un ID de cola
        // Revisar antes si ya tenia un ID asociado a esa cola!
        std::string touchCmd = "touch ";
        touchCmd += m_nombreColaRemota;
        system( touchCmd.c_str() );

        std::ifstream file( m_nombreColaRemota.c_str() );

        if ( ! ( file >> idCola ) || idCola <= 0 )
        {
            idCola = NumeradorService::getNext();

            file.close();
            std::ofstream file2( m_nombreColaRemota.c_str() );
            file2 << idCola;
            file2.close();
        }
        else
        {
            file.close();
        }

        // Envio el id por el socket
        enviar( m_socket, &idCola, sizeof( int ) );

        // Registro el ID de cola con el nombre de la cola
        DNSService::registerName( m_nombreColaRemota, idCola );
    }

public:
    ColaRemotaReceptor( std::string nombreColaRemota ) :
        m_nombreColaRemota( nombreColaRemota ),
        m_socket( 0 )
    {
        _conectar();
    }

    virtual ~ColaRemotaReceptor()
    {
        close( m_socket );
    }

    template< class T >
    T recibirMensaje()
    {
        PaqueteColaRemota msg;
        T dato;
        int ack = 0;

        // espero un paquete del socket
        if ( recibir( m_socket, &msg, sizeof( PaqueteColaRemota ) ) > 0 )
        {
            enviar( m_socket, &ack, sizeof( int ) );

            // tomo el payload
            memcpy( &dato, msg.data, sizeof(T) );
        }
        else
        {
            throw Exception( "El socket se cerro del otro lado!" );
        }

        // lo devuelvo
        return dato;
    }

};
#endif /* COLAREMOTARECEPTOR_H_ */
